package org.zfes.snowier.cloud.zbss.asf.engine;

import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;

import com.arcsoft.face.EngineConfiguration;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.FunctionConfiguration;
import com.arcsoft.face.enums.DetectMode;

public class FaceEngineContainer2 {
	
	private Integer maxEngineSize=20;
	
	private String appId;
	private String sdkKey;
	  
	private LinkedBlockingQueue<FaceEngine> extractFaceEngineQueue;
	
	private LinkedBlockingQueue<FaceEngine> compareFaceEngineQueue;
	
	private LinkedBlockingQueue<FaceEngine> detectFaceEngineQueue ;
	
	private  AtomicLong extractEngineQueueSize=new AtomicLong(0); 
	private  AtomicLong compareEngineQueueSize=new AtomicLong(0); 
	private  AtomicLong detectEngineQueueSize=new AtomicLong(0); 
	

	
	
	public  Optional<FaceEngine> take(EngineType type) {
		try {
			
			switch (type) {
			case extract:
				FaceEngine extractFaceEngine=extractFaceEngineQueue.take();
				extractEngineQueueSize.decrementAndGet();
				return Optional.of(extractFaceEngine);
				
			case compare:
				FaceEngine compareFaceEngine=compareFaceEngineQueue.take();
				compareEngineQueueSize.decrementAndGet();
				return Optional.of(compareFaceEngine);
			case detect:
				FaceEngine detectFaceEngine=compareFaceEngineQueue.take();
				detectEngineQueueSize.decrementAndGet();
				return Optional.of(detectFaceEngine);
			default:
				break;
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return Optional.empty();
	}
	
	public  boolean add(FaceEngine faceEngine,EngineType type) {
		boolean isOk=false;
		switch (type) {
		case extract:
			if(extractEngineQueueSize.intValue() >= maxEngineSize) {
				
				return isOk;
			}
			isOk = extractFaceEngineQueue.add(faceEngine);
			 if(isOk) {
				 extractEngineQueueSize.incrementAndGet();
			 }
			break;
		case compare:
			if(compareEngineQueueSize.intValue() >= maxEngineSize) {
				
				return isOk;
			}
			isOk = compareFaceEngineQueue.add(faceEngine);
			 if(isOk) {
				 compareEngineQueueSize.incrementAndGet();
			 }
			break;
		case detect:
			if(detectEngineQueueSize.intValue() >= maxEngineSize) {
				
				return isOk;
			}
			isOk = detectFaceEngineQueue.add(faceEngine);
			 if(isOk) {
				 detectEngineQueueSize.incrementAndGet();
			 }
			break;
		default:
			break;
		}
		 return isOk;
	}
	

	
    public void init() {


    	this.extractFaceEngineQueue = new LinkedBlockingQueue<FaceEngine>(maxEngineSize);
		
		this.compareFaceEngineQueue = new LinkedBlockingQueue<FaceEngine>(maxEngineSize);
		
		this.detectFaceEngineQueue = new LinkedBlockingQueue<FaceEngine>(maxEngineSize);
		
	     EngineConfiguration engineConfiguration = EngineConfiguration.builder().detectMode(DetectMode.ASF_DETECT_MODE_VIDEO)
      		   .functionConfiguration(
                 FunctionConfiguration.builder()
                         .supportAge(true)
                         .supportFace3dAngle(true)
                         .supportFaceDetect(true)
                         .supportFaceRecognition(true)
                         .supportGender(true)
                         .supportLiveness(true)
                         .build()).build();
	     
		for(int i=0 ; i < maxEngineSize ; i++) {
			
			 FaceEngine  compareFaceEngine = new FaceEngine();
			 compareFaceEngine.active(appId, sdkKey);
			 compareFaceEngine.init(EngineConfiguration.builder().detectMode(DetectMode.ASF_DETECT_MODE_VIDEO)
		      		   .functionConfiguration(
		                       FunctionConfiguration.builder()
		                               .supportAge(true)
		                               .supportFace3dAngle(true)
		                               .supportFaceDetect(true)
		                               .supportFaceRecognition(true)
		                               .supportGender(true)
		                               .supportLiveness(true)
		                               .build()).build()); 
	         compareFaceEngineQueue.add(compareFaceEngine);
	         
	         FaceEngine  extractFaceEngine = new FaceEngine();
	         extractFaceEngine.active(appId, sdkKey);
	         extractFaceEngine.init(EngineConfiguration.builder().detectMode(DetectMode.ASF_DETECT_MODE_VIDEO)
	        		   .functionConfiguration(
	        	                 FunctionConfiguration.builder()
	        	                         .supportAge(true)
	        	                         .supportFace3dAngle(true)
	        	                         .supportFaceDetect(true)
	        	                         .supportFaceRecognition(true)
	        	                         .supportGender(true)
	        	                         .supportLiveness(true)
	        	                         .build()).build());
	         extractFaceEngineQueue.add(extractFaceEngine);
	         
	         FaceEngine  detectFaceEngine = new FaceEngine();
	         detectFaceEngine.active(appId, sdkKey);
	         detectFaceEngine.init(EngineConfiguration.builder().detectMode(DetectMode.ASF_DETECT_MODE_VIDEO)
	        		   .functionConfiguration(
	        	                 FunctionConfiguration.builder()
	        	                         .supportAge(true)
	        	                         .supportFace3dAngle(true)
	        	                         .supportFaceDetect(true)
	        	                         .supportFaceRecognition(true)
	        	                         .supportGender(true)
	        	                         .supportLiveness(true)
	        	                         .build()).build()); 
	         detectFaceEngineQueue.add(detectFaceEngine);
	         
	         
		}
        
         
    }
    
	private static FaceEngineContainer2 dataContainer;
	
	private FaceEngineContainer2(String appId,String sdkKey,Integer engineSize) {
		this.maxEngineSize=engineSize;
		
		this.appId=appId;
		this.sdkKey=sdkKey;
		
		this.init();
	}

	public static FaceEngineContainer2 getInstance(String appId,String sdkKey,Integer engineSize) {
	        if (dataContainer == null) {
	            synchronized (FaceEngineContainer2.class) {
	            	if (dataContainer == null) {
	            		dataContainer = new FaceEngineContainer2(appId,sdkKey,engineSize);
	                }
	            }
	        }
	     return dataContainer;
	 }
	

	
}
